﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace LiteratureManage.Domain.DataBackup
{
    using Castle.Facilities.NHibernateIntegration;
    using NHibernate;

    public class SqlServerDBTableBackupExecutor : IDBTableBackupExecutor
    {
        private const string xp_cmdshellOpen1 = "EXEC sp_configure 'show advanced options', 1;RECONFIGURE;";
        private const string xp_cmdshellOpen2 = "EXEC sp_configure 'xp_cmdshell', 1;RECONFIGURE;";
        private const string xp_cmdshellClose1 = "EXEC sp_configure 'show advanced options', 1;RECONFIGURE;";
        private const string xp_cmdshellClose2 = "EXEC sp_configure 'xp_cmdshell', 0;RECONFIGURE;";

        private string _serverName;
        private string _dbName;
        private string _userName;
        private string _password;

        private ISessionManager _sessionManager;

        public SqlServerDBTableBackupExecutor(
            string serverName,
            string dbName,
            string userName,
            string password,
            ISessionManager sessionManager)
        {
            this._serverName = serverName;
            this._dbName = dbName;
            this._userName = userName;
            this._password = password;
            this._sessionManager = sessionManager;
        }

        #region IDBTableBackupExecutor Members

        public void PostBackup(string queryText, string backupFilePath)
        {
            var bcpCommandText = String.Format(
                "exec {0}..xp_cmdshell 'bcp \"{1}\" queryout {2} -c -U {3} -P {4} -S {5}';",
                this._dbName,
                queryText,
                backupFilePath,
                this._userName,
                this._password,
                this._serverName
                );

            runBCPCommand(bcpCommandText);
        }

        public void PostRestore(string dbTable, string backupFilePath)
        {
            var bcpCommandText = String.Format(
                            "exec {0}..xp_cmdshell 'bcp {1}.dbo.{2} in {3} -c -U {4} -P {5} -S {6}';",
                            this._dbName,
                            this._dbName,
                            dbTable,
                            backupFilePath,
                            this._userName,
                            this._password,
                            this._serverName
                            );

            runBCPCommand(bcpCommandText);
        }

        public void PostReset(string dbTable)
        {
            var commandText = String.Format("delete {0};dbcc checkident({0},reseed,0);", dbTable);
            runCommand(commandText);
        }

        #endregion

        private void runBCPCommand(string bcpCommandText)
        {
            var commandTextBuilder = new StringBuilder();
            commandTextBuilder.Append(xp_cmdshellOpen1);
            commandTextBuilder.Append(xp_cmdshellOpen2);
            commandTextBuilder.Append(bcpCommandText);
            commandTextBuilder.Append(xp_cmdshellClose1);
            commandTextBuilder.Append(xp_cmdshellClose2);

            runCommand(commandTextBuilder.ToString());
        }

        private void runCommand(string commandText)
        {
            using (var session = this._sessionManager.OpenSession())
            {
                using (var command = session.Connection.CreateCommand())
                {
                    command.CommandText = commandText;
                    command.CommandType = System.Data.CommandType.Text;
                    command.ExecuteNonQuery();
                }
            }
        }
    }
}
